import { ExtractionTask, ExtractionResult } from '../types';
import { EventEmitter } from 'events';
import { Worker } from 'worker_threads';
import path from 'path';

export class TaskScheduler extends EventEmitter {
  /**
   * 任务映射表
   * 存储所有添加到调度器的任务，键为任务ID，值为任务对象
   */
  private tasks: Map<string, ExtractionTask>;
  
  /**
   * 工作线程映射表
   * 存储正在执行的任务对应的工作线程，键为任务ID，值为工作线程实例
   */
  private workers: Map<string, Worker>;
  
  /**
   * 最大并发任务数
   * 控制同时执行的任务数量上限
   */
  private maxConcurrentTasks: number;
  
  /**
   * 任务队列
   * 存储等待执行的任务，按优先级排序
   */
  private taskQueue: ExtractionTask[];
  
  /**
   * 队列处理状态标志
   * 表示调度器当前是否正在处理队列中的任务
   */
  private isProcessing: boolean;

  /**
   * 任务调度器构造函数
   * @param maxConcurrentTasks 最大并发任务数，默认为3
   */
  constructor(maxConcurrentTasks: number = 3) {
    super();
    this.tasks = new Map();
    this.workers = new Map();
    this.maxConcurrentTasks = maxConcurrentTasks;
    this.taskQueue = [];
    this.isProcessing = false;
  }

  /**
   * 添加任务到调度器
   * @param task 提取任务
   */
  public async addTask(task: ExtractionTask): Promise<void> {
    // 验证任务参数
    this.validateTask(task);

    // 将任务添加到任务列表
    this.tasks.set(task.taskId, task);

    // 根据优先级添加到队列
    this.addToQueue(task);

    // 开始处理队列
    await this.processQueue();
  }

  /**
   * 取消任务
   * @param taskId 任务ID
   */
  public async cancelTask(taskId: string): Promise<void> {
    const task = this.tasks.get(taskId);
    if (!task) {
      throw new Error(`任务 ${taskId} 不存在`);
    }

    // 从队列中移除
    this.taskQueue = this.taskQueue.filter(t => t.taskId !== taskId);

    // 如果任务正在执行，终止对应的worker
    const worker = this.workers.get(taskId);
    if (worker) {
      await worker.terminate();
      this.workers.delete(taskId);
    }

    // 从任务列表中移除
    this.tasks.delete(taskId);

    // 触发任务取消事件
    this.emit('taskCancelled', taskId);
  }

  /**
   * 获取任务状态
   * @param taskId 任务ID
   */
  public getTaskStatus(taskId: string): 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' {
    const task = this.tasks.get(taskId);
    if (!task) {
      throw new Error(`任务 ${taskId} 不存在`);
    }

    if (this.workers.has(taskId)) {
      return 'running';
    }

    if (this.taskQueue.some(t => t.taskId === taskId)) {
      return 'pending';
    }

    return 'completed';
  }

  /**
   * 验证任务参数
   * @param task 提取任务
   */
  private validateTask(task: ExtractionTask): void {
    if (!task.taskId) {
      throw new Error('任务ID不能为空');
    }

    if (!task.projectId) {
      throw new Error('项目ID不能为空');
    }

    if (!task.sourcePaths || task.sourcePaths.length === 0) {
      throw new Error('源码路径不能为空');
    }

    if (!task.translationConfig) {
      throw new Error('翻译配置不能为空');
    }

    if (!task.translationConfig.scan.defaultLocale) {
      throw new Error('扫描 语言 不能为空');
    }
  }

  /**
   * 将任务添加到队列
   * @param task 提取任务
   */
  private addToQueue(task: ExtractionTask): void {
    // 根据优先级插入到队列中
    const insertIndex = this.taskQueue.findIndex(t => t.priority < task.priority);
    if (insertIndex === -1) {
      this.taskQueue.push(task);
    } else {
      this.taskQueue.splice(insertIndex, 0, task);
    }
  }

  /**
   * 处理任务队列
   */
  private async processQueue(): Promise<void> {
    if (this.isProcessing || this.taskQueue.length === 0) {
      return;
    }

    this.isProcessing = true;

    try {
      while (this.taskQueue.length > 0 && this.workers.size < this.maxConcurrentTasks) {
        const task = this.taskQueue.shift();
        if (!task) break;

        await this.executeTask(task);
      }
    } finally {
      this.isProcessing = false;
    }
  }

  /**
   * 执行任务
   * @param task 提取任务
   */
  private async executeTask(task: ExtractionTask): Promise<void> {
    try {
      // 创建worker
      const worker = new Worker(path.join(__dirname, '../workers/ExtractionWorker.js'), {
        workerData: { task }
      });

      // 保存worker引用
      this.workers.set(task.taskId, worker);

      // 监听worker消息
      worker.on('message', (result: ExtractionResult) => {
        this.handleTaskResult(task.taskId, result);
      });

      // 监听worker错误
      worker.on('error', (error: Error) => {
        this.handleTaskError(task.taskId, error);
      });

      // 监听worker退出
      worker.on('exit', (code: number) => {
        if (code !== 0) {
          this.handleTaskError(task.taskId, new Error(`Worker stopped with exit code ${code}`));
        }
      });

      // 触发任务开始事件
      this.emit('taskStarted', task.taskId);

    } catch (error) {
      this.handleTaskError(task.taskId, error as Error);
    }
  }

  /**
   * 处理任务结果
   * @param taskId 任务ID
   * @param result 提取结果
   */
  private handleTaskResult(taskId: string, result: ExtractionResult): void {
    // 清理worker
    const worker = this.workers.get(taskId);
    if (worker) {
      worker.terminate();
      this.workers.delete(taskId);
    }

    // 触发任务完成事件
    this.emit('taskCompleted', taskId, result);

    // 继续处理队列
    this.processQueue();
  }

  /**
   * 处理任务错误
   * @param taskId 任务ID
   * @param error 错误信息
   */
  private handleTaskError(taskId: string, error: Error): void {
    // 清理worker
    const worker = this.workers.get(taskId);
    if (worker) {
      worker.terminate();
      this.workers.delete(taskId);
    }

    // 触发任务失败事件
    this.emit('taskFailed', taskId, error);

    // 继续处理队列
    this.processQueue();
  }
} 